package com.ihr360.payroll.model.dto.salary.superclass;


import com.ihr360.commons.model.type.FormulaFrom;
import com.ihr360.commons.model.type.RoundingMode;
import com.ihr360.commons.model.type.SalaryFieldValueType;
import com.ihr360.payroll.model.base.salaryreport.ISalaryField;
import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
import com.vladmihalcea.hibernate.type.json.JsonStringType;
import org.hibernate.annotations.TypeDef;
import org.hibernate.annotations.TypeDefs;

import javax.persistence.Column;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.MappedSuperclass;
import java.io.Serializable;
import java.text.Format;

/**
 * 薪资字段取数定义
 *
 * @param <V>
 */
@MappedSuperclass
@TypeDefs({
        @TypeDef(name = "json", typeClass = JsonStringType.class),
        @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
public abstract class AbstractSalaryFieldValue<V extends AbstractSalaryFieldValue<V>>
        implements Serializable, ISalaryField {

    private static final long serialVersionUID = -4887088470519672344L;

    /**
     * 薪酬字段值类型
     */
    @Column(nullable = false)
    @Enumerated(EnumType.STRING)
    protected SalaryFieldValueType valueType = SalaryFieldValueType.NUMBER;

    /**
     * 是否可空
     */
    protected boolean nullable = true;

    /**
     * 最小值
     */
    @Column(name = "min_value")
    protected long minValue = -999999999999999L;

    /**
     * 最大值
     */
    @Column(name = "max_value")
    protected long maxValue = 999999999999999L;

    /**
     * 舍入规则
     */
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    protected RoundingMode roundingMode = RoundingMode.ROUND;

    /**
     * 数值类型时为精确位数
     */
    protected int pattern = 0;

    /**
     * Raw公式定义
     */
    @Column(columnDefinition = "varchar(500)")
    protected String formula;

    /**
     * 公式来源
     */
    @Column(columnDefinition = "varchar(10)")
    @Enumerated(EnumType.STRING)
    protected FormulaFrom formulaFrom;

    /**
     * 公式描述，如果提供不了公式，则需用通过描述告知用户计算逻辑
     */
    @Column(columnDefinition = "varchar(500)")
    protected String formulaMeta;

    /**
     * 分段计薪公式配置
     * 系统目前只支持一个薪资周期内分两段
     */
    @Column(columnDefinition = "varchar(500)")
    protected String phasedFormula;

    /**
     * 合并计税公式
     */
    @Column(columnDefinition = "varchar(500)")
    protected String mergeTaxFormula;


    public SalaryFieldValueType getValueType() {
        return valueType;
    }

    public void setValueType(SalaryFieldValueType valueType) {
        this.valueType = valueType;
    }

    public long getMinValue() {
        return minValue;
    }

    public void setMinValue(long minValue) {
        this.minValue = minValue;
    }

    public long getMaxValue() {
        return maxValue;
    }

    public void setMaxValue(long maxValue) {
        this.maxValue = maxValue;
    }

    public RoundingMode getRoundingMode() {
        return roundingMode;
    }

    public void setRoundingMode(RoundingMode roundingMode) {
        this.roundingMode = roundingMode;
    }

    public int getPattern() {
        return pattern;
    }

    public void setPattern(int pattern) {
        this.pattern = pattern;
    }

    public String getFormula() {
        return formula;
    }

    public void setFormula(String formula) {
        this.formula = formula;
    }

    public String getMergeTaxFormula() {
        return mergeTaxFormula;
    }

    public void setMergeTaxFormula(String mergeTaxFormula) {
        this.mergeTaxFormula = mergeTaxFormula;
    }

    public String getMaxValueStr() {
        Format format = getFormat();
        return format == null ? "" + this.maxValue : format.format(this.maxValue);
    }

    public String getMinValueStr() {
        Format format = getFormat();
        return format == null ? "" + this.minValue : format.format(this.minValue);
    }

    @SuppressWarnings("unchecked")
    //@JSONField(serialize = false)
    public <T extends Format> T getFormat() {
        StringBuilder sb = new StringBuilder("0");
        if (pattern > 0) {
            sb.append(".");
        }
        for (int i = 0; i < pattern; i++) {
            sb.append("0");
        }
        return (T) valueType.getFormat(sb.toString(), roundingMode);
    }

    public boolean isNullable() {
        return nullable;
    }

    public void setNullable(boolean nullable) {
        this.nullable = nullable;
    }

    @Override
    public FormulaFrom getFormulaFrom() {
        return formulaFrom;
    }

    public void setFormulaFrom(FormulaFrom formulaFrom) {
        this.formulaFrom = formulaFrom;
    }

    @Override
    public String getPhasedFormula() {
        return phasedFormula;
    }

    public void setPhasedFormula(String phasedFormula) {

        this.phasedFormula = phasedFormula;
    }

    public String getFormulaMeta() {
        return formulaMeta;
    }

    public void setFormulaMeta(String formulaMeta) {
        this.formulaMeta = formulaMeta;
    }
}
